/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.absisgroup.nsc.utilities;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 *
 * @author Hue
 */
public final class Format {
    /**
     * Grouping size is the number of digits between grouping separators in the integer portion of a number. 
     * For example, in the number "123 456,78", the grouping size is 3. 
     */
    private int groupingSize = 3;
    private String groupingSeparator = " ";
    
    /**
     * Decimal separator or monetary decimal separator 
     */
    private int decimalSize = 2;
    private String decimalSeparator = ",";
    private boolean removeZero = false;
    private boolean bTrimDecimal = false;
    
    public Format(final String pattern) {
        this(pattern, false, false);
    }
    
    public Format(final String pattern, final boolean removeZero) {
        this(pattern, removeZero, false);
    }
    
    public Format(final String pattern, final boolean removeZero, final boolean bTrimDecimal) {
        this.removeZero = removeZero;
        this.bTrimDecimal = bTrimDecimal;
        setPattern(pattern);
    }
    /**
     * Pattern of the bean that contains the data we will be rendering.
     * 
     * Recognized patterns are:
     *   "#X###Y##"
     *   X : grouping Separator
     *   Y : decimal Separator
     *   
     *   Ex: # ###,##
     *       # ###
     *       #,###.## 
     *       #,### 
     */    
    public void setPattern(String pattern) {
        //remove the first character '#'
        pattern = pattern.substring(1);
        //find the groupingSeparator
        int index = pattern.indexOf('#');
        if(index == -1) {
            return;
        }
        groupingSeparator = pattern.substring(0,index);
        pattern = pattern.substring(index + groupingSize);
        index = pattern.indexOf('#');
        if(index == -1) {
            decimalSize = 0;
            return;
        }
        decimalSeparator = pattern.substring(0,index);
        pattern = pattern.substring(index);
        decimalSize = pattern.length();
    }
    
    public String getGroupingSeparator() {
        return groupingSeparator;
    }
    
    public String getDecimalSeparator() {
        return decimalSeparator;
    }
    
    public String format(final Object o) {
        if(o == null) {
            return "";
        }
        try {
            final BigDecimal bd = new BigDecimal(String.valueOf(o));

            return formatNumber(bd);
        }
        catch(NumberFormatException ex) {
            return o.toString();
        }
    }
    
    public String formatNumber(BigDecimal value) {
        if(value == null) {
            return "";
        }
        if( (value.compareTo(new BigDecimal(0)) == 0) && removeZero ) {
            return "0";
        }
        final int signum = value.signum();
        value = value.abs();
        BigDecimal bd = value.setScale(decimalSize, BigDecimal.ROUND_HALF_UP);
        bd = bd.movePointRight(decimalSize);
        final BigInteger bi = bd.toBigInteger();
        String s = bi.toString();
        if(s.length() < decimalSize) {
            final int nPadding = decimalSize - s.length();
            for(int i=0; i<nPadding; i++) {
                s = "0" + s;
            }
        }
        final int len = s.length();
        String decimals = "";
        StringBuffer t = new StringBuffer();
        //
        if(decimalSize > 0) {
            t.append(decimalSeparator);
        }
        for(int i=decimalSize; i>0; i--) {
            final char c = s.charAt(len-i);
            t.append(c);
            decimals += c;
        }
        //Trim zero in decimal
        if(bTrimDecimal && decimals.length() > 0) {
            t = new StringBuffer();
            while(decimals.length() > 0) {
                if(decimals.charAt(decimals.length() - 1) != '0') {
                    break;
                }
                decimals = decimals.substring(0, decimals.length() - 1);
            }
            if(decimals.length() > 0) {
                t.append(decimalSeparator);
                t.append(decimals);
            }
        }
        //
        if(removeZero && decimals.length() > 0) {
            try {
                if(Integer.parseInt(decimals) == 0) {
                    t = new StringBuffer();
                }
            }
            catch(NumberFormatException ex) {
                //do nothing
            }
        }
        int group = 0;

        for (int i=len-decimalSize-1; i>=0; i--) {
            t.insert(0, s.charAt(i));
            group++;
            if (group == groupingSize) {
                t.insert(0, groupingSeparator);
                group = 0;
            }
        }
        String tmp = t.toString();
        //remove the groupingSeparator at the begining of the string
        if(tmp.indexOf(groupingSeparator) == 0) {
            tmp = tmp.substring(groupingSeparator.length());
        }
        tmp = tmp.trim();
        tmp = (tmp.startsWith(decimalSeparator)?("0" + tmp):tmp);

        return (signum<0?("-"+tmp):tmp);
    }

    public BigDecimal getNumber(final String value) {
        BigDecimal bd = new BigDecimal(0);
        if(value == null || "".equals(value)) {
            return bd;
        }
        try {
            bd = new BigDecimal(value);
            bd = bd.setScale(decimalSize, BigDecimal.ROUND_HALF_UP);
        }
        catch(NumberFormatException ex) {
            return bd;
        }
        return bd;
    } // getNumber()
}
